#!/usr/bin/python
# -*- encoding: utf-8 -*-

import unittest
import re

import post

class TestPost(unittest.TestCase):
    def setUp(self):
        pass

    def testOpenTag2EndTag(self):
        self.assertEqual("</ul>", post.open_tag2end_tag("<ul>"))

    def testStripWikiCode(self):
        self.assertEqual(u"中文", post.strip_wiki_code(u"'''中文'''", u"'''"))

    def testParseFontStyle(self):
        tinput_list = [
            # Bold
            u"中文",
            u"'''中文'''",
            u"'''中文'''abc'''2'''no",
            u"abc\n'''12'''345'''678'''9",
            # Strike-through
            u"abc\n~~del~~",
            # Combination
            u"'''bold'''~~strike~~''italic''x^i^,,j,,"
        ]
        toutput_list = [
            # Bold
            u"中文",
            u"<strong>中文</strong>",
            u"<strong>中文</strong>abc<strong>2</strong>no",
            u"abc\n<strong>12</strong>345<strong>678</strong>9",
            # Strike-through
            u"abc\n<del>del</del>",
            # Combination
            u"<strong>bold</strong><del>strike</del><em>italic</em>x<sup>i</sup><sub>j</sub>"
        ]

        for tinput, toutput in zip(tinput_list, toutput_list):
            self.assertEqual(toutput, post.parse_font_style(tinput))
    def testParsePass(self):
        text = '<a href="http://a.b"><img src="http://a.b.jpg" /></a>'
        code_parser = post.CodeParser()
        self.assertEqual(text, code_parser.parse('{{{' + text + '}}}'))

        text = '<a href="http://a.b"><img src="http://a.b.jpg" /></a>'
        code_parser = post.CodeParser()
        self.assertEqual("head %s middle %s tail" % (text, text),
                         code_parser.parse("head {{{%s}}} middle {{{%s}}} tail" % (text, text)))

    def testParseHeading(self):
        tinput_list = [
            u"中文",
            u"=中文=",
            u"=== 中文 =",
            u"= 中文 =",
            u"== 中文 ==",
            u"=== 中文 ===",
            u"==== 中文 ====",
            u"= 中文 =\n123\n== abc =="
        ]
        toutput_list = [
            u"中文",
            u"=中文=",
            u"=== 中文 =",
            u"<h1>中文</h1>",
            u"<h2>中文</h2>",
            u"<h3>中文</h3>",
            u"<h4>中文</h4>",
            u"<h1>中文</h1>\n123\n<h2>abc</h2>"
        ]
        for tinput, toutput in zip(tinput_list, toutput_list):
            self.assertEqual(toutput, post.parse_heading(tinput))

    def testParseUnorderedList(self):
        tinput_list = [
            # no unordered list
            u"中文",
            u"*中文",
            u" *中文",
            # has unordered list
            u" * 中文",
            u" * 中文\n * abc",
            # no list + unordred list 
            u"00\n * 中文\n * abc\ndef",
            # has ordered list
            u" 1. 中文\n 1. abc",
        ]
        toutput_list = [
            # no unordered list
            u"中文",
            u"*中文",
            u" *中文",
            # has unordered list
            u"<ul>\n<li>中文</li>\n</ul>",
            u"<ul>\n<li>中文</li>\n<li>abc</li>\n</ul>",
            # no list + unordred list 
            u"00\n<ul>\n<li>中文</li>\n<li>abc</li>\n</ul>\ndef",
            # has ordered list
            u"<ol>\n<li>中文</li>\n<li>abc</li>\n</ol>",
        ]

        for tinput, toutput in zip(tinput_list, toutput_list):
            self.assertEqual(toutput, post.parse_list(tinput))
        # unordred list + no list + ordered list
        tinput = u"""\
                 * 中文
                000
                 1. abc
                """
        toutput = u"""\
                <ul>
                <li>中文</li>
                </ul>
                000
                <ol>
                <li>abc</li>
                </ol>
                """
        self.assertEqual(smart_lstrip(toutput), post.parse_list(smart_lstrip(tinput)))

    def testParseBlockquote(self):
        tinput_list = [
            u"中文",
            u" 中文",
            u"   中文",
            u"  中文",
            u"  中文\n  abc",
        ]
        toutput_list = [
            u"中文",
            u" 中文",
            u"   中文",
            u"<blockquote>\n中文\n</blockquote>",
            u"<blockquote>\n中文\nabc\n</blockquote>",
        ]

        for tinput, toutput in zip(tinput_list, toutput_list):
            self.assertEqual(toutput, post.parse_blockquote(tinput))

    def testParseCode(self):
        tinput_list = [
            u"中文",
            """\
            {{{
            #!ruby
            print "hi"
            }}}
            """,

            """\
            abc {{{
            #!python
            print "Goooood"
            }}}
            """,

            u"""\
            {{{
            #!python
            print "hi"
            if True:
                pass
            }}}
            """,
        ]
        toutput_list = [
            u"中文",
            """\
            <pre line="1" lang="ruby">
            print "hi"
            </pre>
            """,

            """\
            abc <pre line="1" lang="python">
            print "Goooood"
            </pre>
            """,

            u"""\
            <pre line="1" lang="python">
            print "hi"
            if True:
                pass
            </pre>
            """,
        ]

        code_parser = post.CodeParser()
        for tinput, toutput in zip(tinput_list, toutput_list):
            try:
                self.assertEqual(smart_lstrip(toutput),
                                 code_parser.parse(smart_lstrip(tinput)))
            except SyntaxError, e:
                print tinput.encode('utf8')
                self.fail()
        # test: more than one code
        try:
            tinput = "\n".join(map(smart_lstrip, tinput_list))
            toutput = "\n".join(map(smart_lstrip, toutput_list))
            self.assertEqual(toutput, code_parser.parse(tinput))
        except SyntaxError, e:
            print tinput.encode('utf8')
            self.fail()

        # test list + code
        tinput = """\
                abc
                {{{
                #!java
                // comment
                void foo() {}
                }}}
                """
        toutput = 'abc\n<pre line="1" lang="java">\n// comment\nvoid foo() {}\n</pre>\n'
        try:
            self.assertEqual(smart_lstrip(toutput),
                             code_parser.parse(smart_lstrip(tinput)))
        except SyntaxError, e:
            print tinput
            self.fail()
        # test error handling
        self.assertRaises(SyntaxError, code_parser.parse, u"{{{\n中文\n}}}")

    def testParseCodeQuote(self):
        tinput = """\
                {{{
                #!quote
                print "hi"
                }}}
                """
        toutput = """\
                <blockquote>
                print "hi"
                </blockquote>
                """
        code_parser = post.CodeParser()
        try:
            self.assertEqual(smart_lstrip(toutput),
                             code_parser.parse(smart_lstrip(tinput)))
        except SyntaxError, e:
            print tinput
            self.fail()


    def testParseLink(self):
        tinput_list = [
            'http://fcamel.twbbs.org/',                           # Simple URL
            'my blog: http://fcamel.twbbs.org/ thx',              # Simple URL
            'http://a.b/x.png',                                   # Image URL
            'http://a.org/ http://b.com',                         # Two URL
            u'[http://www.google.com/ 谷歌]',                     # Wiki URL in Chinese
            '[http://www.python.org/ Python Rocks]',              # Wiki URL with two-word title
            '[Python Rocks]',                                     # Cached URL
            u'http://a.b [Python Rocks][谷歌]http://c.d',         # Complicated cases
        ]
        toutput_list  = [
            '<a href="http://fcamel.twbbs.org/">http://fcamel.twbbs.org/</a>',
            'my blog: <a href="http://fcamel.twbbs.org/">http://fcamel.twbbs.org/</a> thx',
            '<img src="http://a.b/x.png" />',
            '<a href="http://a.org/">http://a.org/</a> <a href="http://b.com">http://b.com</a>',
            u'<a href="http://www.google.com/">谷歌</a>',
            '<a href="http://www.python.org/">Python Rocks</a>',
            '<a href="http://www.python.org/">Python Rocks</a>',
            (u'<a href="http://a.b">http://a.b</a> <a href="http://www.python.org/">Python Rocks</a>'
             u'<a href="http://www.google.com/">谷歌</a><a href="http://c.d">http://c.d</a>'),
        ]
        for tinput, toutput in zip(tinput_list, toutput_list):
            out, link_dict = post.parse_link(tinput)
            self.assertEqual(toutput, out)

        tinput = '[pypi]'
        toutput = '<a href="http://www.python.org/pypi">pypi</a>'

        # Test parsing link when the title -> link is not in the dictionary.
        post.flags['ignore_missing_link'] = False
        self.assertRaises(SyntaxError, post.parse_link, tinput)

        # Print WARNING: ... and return the same text.
        post.flags['ignore_missing_link'] = True
        out, link_dict = post.parse_link(tinput)
        self.assertEqual(tinput, out)

        # Test parsing link when the title -> link is in the dictionary.
        post.flags['ignore_missing_link'] = False
        out, link_dict = post.parse_link(tinput, {'pypi': 'http://www.python.org/pypi'})
        self.assertEqual(toutput, out)

    def testParseLinkWithChineseBracket(self):
        tinput_list = [
            u'〔http://www.google.com/ 谷歌〕',
            u'〔谷歌〕',
        ]
        toutput_list  = [
            u'<a href="http://www.google.com/">谷歌</a>',
            u'<a href="http://www.google.com/">谷歌</a>',
        ]

        post.flags['use_chinese_bracket'] = False
        for tinput, toutput in zip(tinput_list, toutput_list):
            out, link_dict = post.parse_link(tinput)
            self.assertNotEqual(toutput, out)

        post.flags['use_chinese_bracket'] = True
        for tinput, toutput in zip(tinput_list, toutput_list):
            out, link_dict = post.parse_link(tinput)
            self.assertEqual(toutput, out)

    def testParse(self):
        # test: simple combination
        tinput = u"""\
                == 中文 ==
                 * abc'''[http://a.b bold]'''
                haha
                """
        toutput = u"""\
                <h2>中文</h2>
                <ul>
                <li>abc<strong><a href="http://a.b">bold</a></strong></li>
                </ul>
                haha
                """
        self.assertEqual(smart_lstrip(toutput), post.parse(smart_lstrip(tinput), False))

        # test: don't parse codes in {{{...}}}
        tinput = u"""\
                {{{
                #!python
                print "[this is not link"]
                }}}
                """
        toutput = u"""\
                <pre line="1" lang="python">
                print "[this is not link"]
                </pre>
                """
        try:
            self.assertEqual(smart_lstrip(toutput), post.parse(smart_lstrip(tinput), False))
        except SyntaxError, e:
            self.fail(e.message)

    def testParseListAndCode(self):
        # test: list + code
        tinput = """\
             * demo: {{{
            #!java
            // comment
            void foo() {}
            }}}
             * hard test"""
        toutput = """\
            <ul>
            <li>demo: <pre line="1" lang="java">
            // comment
            void foo() {}
            </pre></li>
            <li>hard test</li>
            </ul>"""
        self.assertEqual(smart_lstrip(toutput), post.parse(smart_lstrip(tinput), False))

        # test: list, code, list
        tinput = """\
             * list first
            demo: {{{
            #!java
            // comment
            void foo() {}
            }}}
             * hard test"""
        toutput = """\
            <ul>
            <li>list first</li>
            </ul>
            demo: <pre line="1" lang="java">
            // comment
            void foo() {}
            </pre>
            <ul>
            <li>hard test</li>
            </ul>"""
        self.assertEqual(smart_lstrip(toutput), post.parse(smart_lstrip(tinput), False))

    def testCarriageReturn(self):
        self.assertEqual("<h1>title</h1>", post.parse("= title =", False))
        self.assertEqual("<h1>title</h1>", post.parse("= title =\r", False))


def smart_lstrip(text):
    def find_left_spaces(lines):
        return [len(re.findall("^ *", line)[0]) for line in lines]

    lines = text.split("\n")
    indent_length = min(find_left_spaces(lines))
    lines = [line[indent_length:] for line in lines]
    return "\n".join(lines)


if __name__ == '__main__':
    unittest.main()
